package com.holly.unit.deform.util;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.holly.unit.deform.api.callback.DesformRecursive;
import com.holly.unit.deform.api.enums.WidgetTypeEnum;
import com.holly.unit.deform.api.pojo.tool.ConvertItem;
import com.holly.unit.deform.api.pojo.tool.DesformConverter;
import com.holly.unit.deform.api.pojo.tool.DesformWidget;
import com.holly.unit.deform.context.DeformContext;
import com.holly.unit.deform.entity.DesignForm;
import com.holly.unit.deform.entity.DesignFormData;
import com.holly.unit.es.api.EsApi;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 类描述:
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/5 11:14
 */
@Slf4j
public class DeformUtil {

    private static EsApi esApi = DeformContext.esApi();


    /**
     * 递归调用处理所有的组件（包括栅格或其他容器组件内的组件）
     *
     * @param dataList
     * @param callback 需要自实现的回调函数
     */
    public static void recursiveAllWidget(JSONArray dataList, DesformRecursive callback) {
        recursiveAllWidget(dataList, null, callback);
    }

    /**
     * 递归调用处理所有的组件（包括栅格或其他容器组件内的组件）
     *
     * @param array
     * @param parent
     * @param callback 需要自实现的回调函数
     */
    public static void recursiveAllWidget(JSONArray array, JSONObject parent, DesformRecursive callback) {
        for (int i = 0; i < array.size(); i++) {
            JSONObject item = array.getJSONObject(i);
            WidgetTypeEnum type = WidgetTypeEnum.getByValue(item.getString("type"));
            // 判断是否是栅格或其他容器组件
            Boolean isContainer = item.getBoolean("isContainer");
            if (isContainer != null && isContainer) {
                if (item.get("columns") != null) {
                    JSONArray columns = item.getJSONArray("columns");
                    for (int j = 0; j < columns.size(); j++) {
                        JSONObject column = columns.getJSONObject(j);
                        recursiveAllWidget(column.getJSONArray("list"), item, callback);
                    }
                } else if (WidgetTypeEnum.CARD == type) {
                    recursiveAllWidget(item.getJSONArray("list"), item, callback);
                } else if (WidgetTypeEnum.TABS == type) {
                    JSONArray panes = item.getJSONArray("panes");
                    for (int j = 0; j < panes.size(); j++) {
                        JSONObject pane = panes.getJSONObject(j);
                        recursiveAllWidget(pane.getJSONArray("list"), item, callback);
                    }
                }
            }
            // 执行回调函数
            if (callback != null) {
                callback.execute(type, item, parent);
            }
        }
    }

    /**
     * 获取设计JSON
     */
    public static JSONObject getDesformJSON(DesignForm designForm) {
        return JSON.parseObject(designForm.getDesformDesignJson());
    }

    public static JSONArray getDataList(DesignForm designForm) {
        return getDataList(getDesformJSON(designForm));
    }

    /**
     * 获取设计JSON的list
     */
    public static JSONArray getDataList(JSONObject desformJSON) {
        return desformJSON.getJSONArray("list");
    }

    public static JSONObject getConfig(DesignForm designForm) {
        return getConfig(getDesformJSON(designForm));
    }

    /**
     * 获取设计JSON的config
     */
    public static JSONObject getConfig(JSONObject desformJSON) {
        return desformJSON.getJSONObject("config");
    }



    /**
     * 判断给定的组件是否不是数据组件，即仅供展示不存储数据的组件
     */
    public static boolean isNotDataWidget(WidgetTypeEnum type) {
        if(type==null){return false;}
        switch (type) {
            case GRID:
            case CARD:
            case TABS:
            case TEXT:
            case BLANK:
            case BUTTON:
            case BUTTONS:
            case DIVIDER:
            case SUB_TABLE_DESIGN:
                return true;
            default:
                return false;
        }
    }


    // 外部模拟登陆临时账号密码
    private static final String EXTERNAL_USERNAME = "_reserve_user_external";
    private static final String EXTERNAL_PASSWORD = "holly@123";



    /**
     * 异步执行方法
     */
    public static Thread asyncMethod(Runnable target) {
        Thread t = new Thread(target);
        try {
            t.start();
        } catch (Exception e) {
            log.error("异步方法执行失败：" + e.getMessage());
        }
        return t;
    }

    /**
     * 异步创建 ElasticSearch 索引
     *
     * @param desformCode
     */
    public static void asyncCreateEsIndex(String desformCode) {
        asyncMethod(() -> {
            try {
                esApi.createIndex(desformCode);
            } catch (Exception e) {
                log.warn("ES索引创建失败：" + e.getMessage());
            }
        });
    }

    /**
     * 异步删除 ElasticSearch 索引
     *
     * @param desformCode
     */
    public static void asyncRemoveEsIndex(String desformCode) {
        asyncMethod(() -> {
            try {
                esApi.removeIndex(desformCode);
            } catch (Exception e) {
                log.warn("ES索引删除失败：" + e.getMessage());
            }
        });
    }

    /**
     * 异步保存或更新 ElasticSearch 索引数据
     *
     * @param desformCode
     * @param data
     */
    public static void asyncSaveOrUpdateEsIndex(String desformCode, DesignFormData data) {
        asyncMethod(() -> {
            try {
                log.info("异步保存或更新 ElasticSearch 索引数据，desformCode= "+desformCode+"，designFormData= "+data.toString());
                esApi.saveOrUpdate(desformCode, "design_form", data.getId(), JSON.parseObject(data.getDesformDataJson()));
            } catch (Exception e) {
                log.warn("ES索引数据保存失败：" + e.getMessage());
            }
        });
    }

    /**
     * 异步删除 ElasticSearch 索引数据
     *
     * @param desformCode
     * @param data
     */
    public static void asyncDeleteEsIndex(String desformCode, DesignFormData data) {
        asyncMethod(() -> {
            try {
                esApi.delete(desformCode, "design_form", data.getId());
            } catch (Exception e) {
                log.warn("ES索引数据删除失败：" + e.getMessage());
            }
        });
    }

    /**
     * 获取所有需要转换的组件的转换器，map的key是组件的modal，value是转换器方法
     *
     * @return
     */
    public static Map<String, ConvertItem> getConvertersIfNeed(JSONArray dataList) {
        Map<String, ConvertItem> converters = new HashMap<>();
        recursiveAllWidget(dataList, (type, item, parent) -> {
            String model = item.getString("model");
            ConvertItem convertItem = new ConvertItem(model, item);
            // 判断类型是否需要转换
            if (WidgetTypeEnum.DATE == type) {

                convertItem.setConverter(DesformConverter::formatDate);
            } else if (WidgetTypeEnum.TIME == type) {
                convertItem.setConverter(DesformConverter::formatTime);
            } else if (WidgetTypeEnum.NUMBER == type) {
                convertItem.setConverter(DesformConverter::formatNumber);
            }
            // 需要转换的放进转转换器Map里
            if (convertItem.getConverter() != null) {
                converters.put(model, convertItem);
            }
        });
        return converters;
    }

    /**
     * 通过实体获取组件列表
     */
    public static List<DesformWidget> getDesformWidgetListByEntity(DesignForm designForm) {
        if (designForm == null) {
            return null;
        }
        String desJSON = designForm.getDesformDesignJson();
        if (StrUtil.isBlank(desJSON)) {
            return null;
        }
        JSONObject desformJSON = JSON.parseObject(desJSON);
        JSONArray dataList = desformJSON.getJSONArray("list");
        return DeformUtil.getDesformWidgetListByDataList(dataList);
    }

    /**
     * 通过实体获取组件列表
     */
    public static List<DesformWidget> getDesformWidgetListByDataList(JSONArray dataList) {
        if (dataList == null) {
            return null;
        }
        List<DesformWidget> desformWidgetList = new ArrayList<>();
        recursiveAllWidget(dataList, (type, item, parent) -> {
            DesformWidget widget = item.toJavaObject(DesformWidget.class);
            widget.setType(type);
            desformWidgetList.add(widget);
        });
        return desformWidgetList;
    }




















}
